package com.test.drawing;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

import com.test.loading.Scene;

/**
 * MeshBuffer<br>
 * Holds all Buffers needed for an OpenGL Mesh
 */
public class MeshBuffer {
	
	private static final int SHORT_BYTE_SIZE = 2;
	protected static final int FLOAT_BYTE_SIZE = 4;
	
	// Our vertex buffer.
	private FloatBuffer mVerticesBuffer = null;

	// Our index buffer.
	private ShortBuffer mIndicesBuffer = null;
	private int indicesSize;

	// Our UV texture buffer.
	private FloatBuffer mTextureBuffer;

	// Our Normal buffer
	private FloatBuffer mNormalBuffer = null;
	
	/**
	 * MeshBuffer Constructor
	 * 
	 * @param scene
	 *            Scene to be used this MeshBuffer<br>
	 *            Vertices, Indices, Textures and Normals are taken from the
	 *            Scene
	 */
	public MeshBuffer(Scene signScene) {
		setScene(signScene);
	}
	
	/**
	 * To be done
	 * @param createScene
	 */
	public void setScene(Scene scene) {
		setVertices(scene.getFrames()[0].getVertices());
		setIndices(scene.getIndices());
		setNormals(scene.getNormalsCoordinates());
		setTextureCoordinates(scene.getTextureCoordinates());
	}

	/**
	 * Gets the Indices Buffer Size of this MeshBuffer
	 * @return int - Indices Buffer Size
	 */
	public int getIndiceSize() {
		return indicesSize;
	}

	/**
	 * Gets the Normal Buffer of this MeshBuffer
	 * @return FloatBuffer - NormalsBuffer
	 */
	public FloatBuffer getNormalBuffer() {
		return mNormalBuffer;
	}

	/**
	 * Gets the Texture Buffer of this MeshBuffer
	 * @return FloatBuffer - TextureBuffer
	 */
	public FloatBuffer getTextureBuffer() {
		return mTextureBuffer;
	}

	/**
	 * Gets the Vertices Buffer of this MeshBuffer
	 * @return FloatBuffer - Vertices Buffer
	 */
	public FloatBuffer getVerticesBuffer() {
		return mVerticesBuffer;
	}

	/**
	 * Gets the Indices Buffer of this MeshBuffer
	 * @return ShortBuffer - Indices Buffer
	 */
	public ShortBuffer getIndicesBuffer() {
		return mIndicesBuffer;
	}
	
	public boolean hasTextureBuffer() {
		return mTextureBuffer != null;
	}
	
	public boolean hasNormalBuffer() {
		return mNormalBuffer != null;
	}
	

	private void setIndices(short[] indices) {
		// short is 2 bytes, therefore we multiply the number if
		// vertices with 2.
		ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length
				* SHORT_BYTE_SIZE);
		ibb.order(ByteOrder.nativeOrder());
		mIndicesBuffer = ibb.asShortBuffer();
		mIndicesBuffer.put(indices);
		mIndicesBuffer.position(0);
		indicesSize = indices.length;
	}

	private void setTextureCoordinates(float[] textureCoords) {
		// float is 4 bytes, therefore we multiply the number if
		// vertices with 4.
		ByteBuffer byteBuf = ByteBuffer.allocateDirect(textureCoords.length
				* FLOAT_BYTE_SIZE);
		byteBuf.order(ByteOrder.nativeOrder());
		mTextureBuffer = byteBuf.asFloatBuffer();
		mTextureBuffer.put(textureCoords);
		mTextureBuffer.position(0);
	}
	
	private void setNormals(float[] normals) {
		if (normals == null || normals.length == 0) return;
		// a float is 4 bytes, therefore we multiply the number if
		// vertices with 4.
		ByteBuffer vbb = ByteBuffer.allocateDirect(normals.length
				* FLOAT_BYTE_SIZE);
		vbb.order(ByteOrder.nativeOrder());
		mNormalBuffer = vbb.asFloatBuffer();
		mNormalBuffer.put(normals);
		mNormalBuffer.position(0);
	}

	private void setVertices(float[] vertices) {
		// a float is 4 bytes, therefore we multiply the number if
		// vertices with 4.
		ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
		vbb.order(ByteOrder.nativeOrder());
		mVerticesBuffer = vbb.asFloatBuffer();
		mVerticesBuffer.put(vertices);
		mVerticesBuffer.position(0);
	}
}
